package com.example.shiro_realy.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        System.out.println("执行 shiroFilterFactoryBean.shiroFilter");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //必须设置SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //需要登录得接口，如果访问某个接口，需要登录却没有登录，则调用此接口（如果不是前后端分离项目，可以直接跳转到其他页面）
        shiroFilterFactoryBean.setLoginUrl("/pub/need_login");
        //登录成功后要跳转得位置，如果前后端分离，则没有这个调用
        shiroFilterFactoryBean.setSuccessUrl("/pub/index");
        //登录成功，但是没有权限，则调用此接口
        shiroFilterFactoryBean.setUnauthorizedUrl("/pub/not_permit");

        //设置自定义的filter
        Map<String , Filter> filters = new LinkedHashMap<>();
        filters.put("roleOrFilter", new CustomRolesOrAuthorizationFilter());
        //将自定义的filter与shiro绑定
        shiroFilterFactoryBean.setFilters(filters);

        //拦截器路径，部分路径无法拦截，时有时无，因为设置的是hashmap，应该使用link
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //退出过滤器
        filterChainDefinitionMap.put("/logout", "logout");
        //匿名可访问过滤器
        filterChainDefinitionMap.put("/pub/**", "anon");
        //需登录才可访问过滤器
        filterChainDefinitionMap.put("/authc/**", "authc");
        //管理员才可登录过滤器
        filterChainDefinitionMap.put("/admin/**", "roleOrFilter[admin,root]");
        //有编辑权限才可以访问过滤器
        filterChainDefinitionMap.put("/video/update", "perms[video_update]");

        //过滤器得执行是从上到下得，一般/**所有路径都可访问，需要放在下面
        //authc：url必须通过认证才能访问
        //anon：url可以匿名访问
        //放在最下面为了拦截上面没有拦截到的路径
        filterChainDefinitionMap.put("/**", "authc");
        //将设置得拦截器加入到shiro中
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;

    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //如果不是前后端分离，可以不用设置下面得sessionManager，注释掉即可
        securityManager.setSessionManager(sessionManager());
        //设置realm（推荐放在最后，不然有些情况会不调用）
        securityManager.setRealm(customRealm());
        return securityManager;
    }
    //自定义realm
    @Bean
    public CustomRealm customRealm(){
        CustomRealm customRealm = new CustomRealm();
        customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return customRealm;
    }

    //密码加解密
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        //散列的次数，比如散列两次，相当于 md5(md5(""));
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }

    @Bean
    public SessionManager sessionManager(){
        CustomSessionManager customSessionManager = new CustomSessionManager();
        //设置会话超时时间，单位是毫秒，默认30分钟
        customSessionManager.setGlobalSessionTimeout(1000*60*30);
        return customSessionManager;
    }
}
